/* Create by Yunhao45
    2025-10-7 */

// 引用系统头文件
#include <string>
#include <windows.h>
#include <commctrl.h>
#include <string>
#include <random>
#include <fstream>
#include <filesystem>
// 引用自定义头（源）文件
#include "YunUtility.hpp"
#include "MainWindow.hpp"
#include "GameWindow.hpp"
#include "RankingListWindow.hpp"
#include "Color.hpp"
// 引用第三方库
#include "nlohmann/json.hpp"
// 定义控件ID
#define ID_START_GAME_BUTTON 1000
#define ID_RANKING_LIST_BUTTON 1001

// 全局变量定义
// --主窗口句柄
HWND hWnd;
HINSTANCE hInst;
const wchar_t MAIN_WINDOW_CLASS_NAME[] = L"GuessColorGame_MainWindow";
// --游戏设置选项句柄
HWND UsernameInputBox;
std::wstring Username;
HWND CardCountTrackbar;
int CardCount = 6; // 默认卡牌数量
// --游戏窗口句柄
HWND GameWindow;
const wchar_t GAME_WINDOW_CLASS_NAME[] = L"GuessColorGame_GameWindow";
// --排行榜窗口句柄
HWND RankingListWindow;
const wchar_t RANKING_LIST_WINDOW_CLASS_NAME[] = L"GuessColorGame_RankingListWindow";
// --游戏数据
nlohmann::json GameData;

// 结构体定义变量
MainWindowAttributes st_mwa;

// 窗口过程函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    int gap = 30; // 上下间距
    switch (uMsg) {
    case WM_CREATE: {
        // 初始化程序
        // -- 设置图标
        LoadAppIcon(hWnd);
        // -- 获取窗口大小
        GetClientRect(hWnd, &st_mwa.rect);
        st_mwa.width = st_mwa.rect.right - st_mwa.rect.left;
        st_mwa.width_center = st_mwa.width / 2;
        st_mwa.height = st_mwa.rect.bottom - st_mwa.rect.top;
        st_mwa.height_center = st_mwa.height / 2;

        // -- 游戏设置选项
        int GameOptionOperationBoxX = 200; // 游戏设置选项操作框x坐标
        // ---- 用户名输入框（绘制提示语的代码请跳转WM_PAINT）
        UsernameInputBox = CreateWindowEx(
            0,
            L"EDIT",
            L"",
            WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_AUTOHSCROLL,
            GameOptionOperationBoxX + 160 /*<-自定义左偏移量+字体总宽度*/,
            st_mwa.height_center - 17 /*<-16号字体高度*/ - (60 - 1) /*<-自定义上偏移量*/,
            160 /*<-字体总宽度*/,
            20 /*<-16号字体高度*/,
            hWnd,
            NULL,
            hInst,
            NULL);
        // <- 设置输入框字体
        SendMessage(UsernameInputBox, WM_SETFONT, (WPARAM)CreateFontSize(16), TRUE);

        // ---- 卡牌数量滑动条（绘制提示语的代码请跳转WM_PAINT）
        CardCountTrackbar = CreateWindowEx(
            0,
            TRACKBAR_CLASS,
            L"",
            WS_CHILD | WS_VISIBLE | TBS_HORZ | TBS_TOOLTIPS,
            GameOptionOperationBoxX + 160,                   // x坐标：用户名输入框右侧
            st_mwa.height_center - 17 - (60 - 1) + gap + 17, // y坐标：用户名输入框下方
            160,                                             // 宽度
            20,                                              // 高度
            hWnd,
            NULL,
            hInst,
            NULL);
        // <- 设置滑动条范围3-10，步长为1
        SendMessage(CardCountTrackbar, TBM_SETRANGE, TRUE, MAKELONG(3, 10));
        SendMessage(CardCountTrackbar, TBM_SETPAGESIZE, 0, 1);
        SendMessage(CardCountTrackbar, TBM_SETPOS, TRUE, CardCount);
        SendMessage(CardCountTrackbar, TBM_SETTICFREQ, 1, 0);

        // -- 开始游戏按钮
        HWND StartGameButton = CreateWindowEx(
            0,
            L"BUTTON",
            L"开始游戏",
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            GetCenterWidth(st_mwa.width, 200),
            st_mwa.height_center + 84 /*自定义下偏移量*/,
            200,
            30,
            hWnd,
            (HMENU)ID_START_GAME_BUTTON,
            hInst,
            NULL);
        // <- 设置按钮字体
        SendMessage(StartGameButton, WM_SETFONT, (WPARAM)CreateFontSize(20), TRUE);

        // -- 排行榜按钮
        HWND RankingListButton = CreateWindowEx(
            0,
            L"BUTTON",
            L"排行榜",
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            st_mwa.width - 90 /*按钮宽度*/ - 10 /*间距*/,
            10 /*间距*/,
            90,
            30,
            hWnd,
            (HMENU)ID_RANKING_LIST_BUTTON,
            hInst,
            NULL);
        // <- 设置按钮字体
        SendMessage(RankingListButton, WM_SETFONT, (WPARAM)CreateFontSize(20), TRUE);

        if (std::filesystem::exists("config/GameData.json")) {
            // 初始化游戏数据
            std::ifstream file("config/GameData.json");
            // 从文件流解析JSON
            GameData = nlohmann::json::parse(file);
            file.close();
        }
        return 0;
    }
    case WM_COMMAND: {
        // 处理按钮点击事件
        if (HIWORD(wParam) == BN_CLICKED) {
            switch (LOWORD(wParam)) {
            case ID_START_GAME_BUTTON: {
                // 获取用户名
                if (Username.empty()) {
                    MessageBox(hWnd, L"请输入用户名", L"错误", MB_OK | MB_ICONERROR);
                    break;
                }

                // 生成颜色并创建InitialCardsColor（保持顺序）
                std::vector<CardsAttributes> colors = GenerateDistinctColors(CardCount);
                InitialCardsColor.clear();
                for (int i = 0; i < CardCount; i++) {
                    CardsAttributes card = colors[i];
                    card.id = i + 1; // 设置顺序id（从1开始）
                    InitialCardsColor.push_back(card);
                }

                // 创建TargetCardsColor（使用Fisher-Yates洗牌算法打乱）
                // 创建索引向量
                std::vector<int> indices(CardCount);
                for (int i = 0; i < CardCount; i++) {
                    indices[i] = i + 1; // 从1开始的ID
                }

                // 使用Fisher-Yates洗牌算法打乱索引
                std::random_device rd;
                std::mt19937 gen(rd());
                for (int i = CardCount - 1; i > 0; i--) {
                    std::uniform_int_distribution<int> dist(0, i);
                    int j = dist(gen);
                    std::swap(indices[i], indices[j]);
                }

                // 使用打乱后的索引创建TargetCardsColor
                TargetCardsColor.clear();
                for (int i = 0; i < CardCount; i++) {
                    CardsAttributes card = colors[i];
                    card.id = indices[i]; // 设置打乱后的id
                    TargetCardsColor.push_back(card);
                }

                // 如果已有游戏窗口，先销毁它
                if (GameWindow != NULL) {
                    DestroyWindow(GameWindow);
                    GameWindow = NULL;
                }

                // 创建新的游戏窗口，通过lpParam传递卡牌数量
                GameWindow = CreateWindowEx(
                    0,
                    GAME_WINDOW_CLASS_NAME,
                    L"猜颜色小游戏",
                    WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
                    CW_USEDEFAULT, CW_USEDEFAULT, 1000 /*游戏窗口宽度*/, 600,
                    NULL,
                    NULL,
                    hInst,
                    reinterpret_cast<LPVOID>(CardCount)); // 传递卡牌数量作为参数
                // 显示游戏窗口
                ShowWindow(GameWindow, SW_SHOW);
                UpdateWindow(GameWindow);
                // 隐藏主窗口
                ShowWindow(hWnd, SW_HIDE);
                break;
            }
            case ID_RANKING_LIST_BUTTON: {
                // 如果已有排行榜窗口，先销毁它
                if (RankingListWindow != NULL) {
                    DestroyWindow(RankingListWindow);
                    RankingListWindow = NULL;
                }

                // 创建新的排行榜窗口
                RankingListWindow = CreateWindowEx(
                    0,
                    RANKING_LIST_WINDOW_CLASS_NAME,
                    L"排行榜",
                    WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
                    CW_USEDEFAULT, CW_USEDEFAULT, 800 /*排行榜窗口宽度*/, 600,
                    NULL,
                    NULL,
                    hInst,
                    NULL);
                // 显示排行榜窗口
                ShowWindow(RankingListWindow, SW_SHOW);
                UpdateWindow(RankingListWindow);
                // 隐藏主窗口
                ShowWindow(hWnd, SW_HIDE);
                break;
            }
            }
        }
        // 获取输入框内容
        if (HIWORD(wParam) == EN_CHANGE) {
            HWND hEdit = (HWND)lParam;
            if (hEdit == UsernameInputBox) {
                // 获取文本长度
                int textLength = GetWindowTextLength(hEdit);

                // 使用std::wstring动态管理内存
                std::wstring buffer(textLength + 1, L'\0');
                GetWindowText(hEdit, &buffer[0], textLength + 1);
                buffer.resize(textLength); // 移除末尾的null字符

                // buffer现在包含动态大小的文本
                // 转移到全局变量
                Username = buffer;
            }
        }
        break;
    }

    case WM_HSCROLL: {
        HWND hTrackbar = (HWND)lParam;
        if (hTrackbar == CardCountTrackbar) {
            CardCount = SendMessage(hTrackbar, TBM_GETPOS, 0, 0);
            // 可以在这里添加卡牌数量变化的处理逻辑
            InvalidateRect(hWnd, NULL, TRUE); // 重绘窗口以更新显示
        }
        break;
    }
    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);

        // 创建字体
        HFONT hFont24 = CreateFontSize(24);
        HFONT hFont20 = CreateFontSize(20);

        // 设置文本颜色和背景
        SetTextColor(hdc, RGB(0, 0, 0)); // 黑色文本
        SetBkMode(hdc, TRANSPARENT);     // 透明背景

        // 选择字体到设备上下文
        HFONT hOldFont24 = (HFONT)SelectObject(hdc, hFont24);
        // 绘制文本（窗口主标题）
        RECT MainWindowTitleRect = {10, 10, st_mwa.width, 50};
        DrawText(hdc, L"猜颜色小游戏", -1, &MainWindowTitleRect,
                 DT_LEFT | DT_TOP | DT_SINGLELINE);
        SelectObject(hdc, hOldFont24); // 恢复原字体

        int GameOptionLabelX = 250; // 游戏设置选项标签的x坐标

        // 绘制文本（游戏设置选项--输入游戏用户名）
        HFONT hOldFont16_1 = (HFONT)SelectObject(hdc, hFont20);
        RECT GameSettingsSubOptionsRect = {GameOptionLabelX, st_mwa.height_center - 17 /*<-16号字体高度*/ - 60 /*<-自定义上偏移量*/, GameOptionLabelX + 160 /*<-字体总宽度*/, st_mwa.height_center + 17 /*<-16号字体高度*/};
        DrawText(hdc, L"输入游戏用户名：", -1, &GameSettingsSubOptionsRect,
                 DT_LEFT | DT_TOP | DT_SINGLELINE);
        SelectObject(hdc, hOldFont16_1);
        // 创建文本输入框的代码请跳转WM_CREATE

        // 绘制文本（游戏设置选项--选择卡牌数量+显示当前选择卡牌数量）
        HFONT hOldFont16_2 = (HFONT)SelectObject(hdc, hFont20);
        RECT GSSOR_2 = GameSettingsSubOptionsRect;
        GSSOR_2.top += 17 + /*<-16号字体高度*/ gap /*<-上下间距*/;
        DrawText(hdc, L"选择卡牌数量：", -1, &GSSOR_2,
                 DT_LEFT | DT_TOP | DT_SINGLELINE);
        RECT GSSOR_3 = GSSOR_2;
        GSSOR_3.left = GameOptionLabelX + (160 - 45) /*标签宽度-自定义左偏移量*/ + 160 /*滑动条宽度*/;
        GSSOR_3.right = GSSOR_3.left + 50;
        GSSOR_3.top = GSSOR_2.top;
        std::wstring cardCountText = std::to_wstring(CardCount) + L"张";
        DrawText(hdc, cardCountText.c_str(), -1, &GSSOR_3,
                 DT_LEFT | DT_TOP | DT_SINGLELINE);
        SelectObject(hdc, hOldFont16_2);
        // 创建范围滑动条的代码请跳转WM_CREATE

        // 删除新字体
        DeleteObject(hFont24);
        DeleteObject(hFont20);

        EndPaint(hWnd, &ps);
        return 0;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_USER + 100:
        // 游戏全部正确后显示主窗口和恭喜消息
        ShowWindow(hWnd, SW_SHOW);
        MessageBox(hWnd, L"恭喜你，全部正确！", L"提示", MB_OK);
        return 0;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

// 注册主窗口类
BOOL RegisterWindowClass() {
    WNDCLASS wc = {};

    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInst;
    wc.lpszClassName = MAIN_WINDOW_CLASS_NAME;
    wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    return RegisterClass(&wc);
}

// 注册游戏窗口类
BOOL RegisterGameWindowClass() {
    WNDCLASS wc = {};

    wc.lpfnWndProc = GameWindowProc;
    wc.hInstance = hInst;
    wc.lpszClassName = GAME_WINDOW_CLASS_NAME;
    wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    return RegisterClass(&wc);
}

// 注册排行榜窗口类
BOOL RegisterRankingListWindowClass() {
    WNDCLASS wc = {};

    wc.lpfnWndProc = RankingListWindowProc;
    wc.hInstance = hInst;
    wc.lpszClassName = RANKING_LIST_WINDOW_CLASS_NAME;
    wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

    return RegisterClass(&wc);
}

// 程序入口点
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    // 消除未使用参数警告
    (void)hPrevInstance;
    (void)lpCmdLine;

    hInst = hInstance;

    // 初始化Common Controls库（用于Trackbar等控件）
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_BAR_CLASSES;
    InitCommonControlsEx(&icex);

    // 注册主窗口类
    if (!RegisterWindowClass()) {
        MessageBox(NULL, L"主窗口类注册失败!", L"错误", MB_ICONERROR);
        return 1;
    }

    // 注册游戏窗口类
    if (!RegisterGameWindowClass()) {
        MessageBox(NULL, L"游戏窗口类注册失败!", L"错误", MB_ICONERROR);
        return 1;
    }

    // 注册排行榜窗口类
    if (!RegisterRankingListWindowClass()) {
        MessageBox(NULL, L"排行榜窗口类注册失败!", L"错误", MB_ICONERROR);
        return 1;
    }

    // 创建窗口
    hWnd = CreateWindowEx(
        0,
        MAIN_WINDOW_CLASS_NAME,
        L"猜颜色小游戏",
        WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
        CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
        NULL,
        NULL,
        hInst,
        NULL);
    if (hWnd == NULL) {
        MessageBox(NULL, L"窗口创建失败!", L"错误", MB_ICONERROR);
        return 1;
    }

    // 显示窗口
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    // 消息循环
    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}